package servidor;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.rmi.RemoteException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

import utilidades.ManipulaArquivos;

/**
 * 
 * @author Douglas Borges
 * 
 */
public class ServidorServicos implements InterfaceServicos {
  public ServidorServicos() throws java.rmi.RemoteException {
    super();
  }


  public String executeC(String maquina, StringBuilder fout) throws java.rmi.RemoteException {
    Runtime runtime = Runtime.getRuntime();
    Process process;
    String console = "";

    File f = setFile(fout, maquina);
    String fileName = f.getName();
    Saida s1 = new Saida();
    try {
      String cmd = "";
      if (fileName.endsWith(".c"))
        cmd = String.format("gcc %s -o %s", f.getAbsolutePath(), f // flag
            // para
            // C
            .getAbsolutePath().replace(".c", ""));
      else
        cmd = String.format("g++ %s -o %s", fileName, // flag para C++
            fileName.replace(".cpp", ""));

      System.out.println(String.format("A maquina '%s' executou o comando\n'%s' ", maquina, cmd));

      process = runtime.exec(cmd);

      s1.saida = new Scanner(process.getInputStream());
      s1.err = new Scanner(process.getErrorStream());

      while (s1.getSaida().hasNext())
        console += new String(("\n" + s1.getSaida().nextLine()).getBytes(), "UTF-8");

      while (s1.getErr().hasNext())
        console += new String(("\n" + s1.getErr().nextLine()).getBytes(), "UTF-8");

      if (console == null || console.isEmpty()) {

        if (fileName.endsWith(".c"))
          cmd = String.format("/home/RMI/%s/./%s", maquina, fileName.replace(".c", ""));
        else
          cmd = String.format("/home/RMI/%s/./%s", maquina, fileName.replace(".cpp", ""));

        process = runtime.exec(cmd);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;

        while ((line = bufferedReader.readLine()) != null)
          console += line + "\n";

        System.out.println(console);
      }
      process.destroy();

      console = console.replaceAll(".*/", "").replaceAll("\n", "").trim();
      String ktemp[] = console.split(" ");
      String ktemp2 = "Compilado com sucesso!!!\nResultado do Programa:\n\n\n";
      int linha = 1;
      for (int u = 0; u < ktemp.length; u++) {
        ktemp2 += ktemp[u] + " ";
        if (ktemp2.length() - 50 > 70 * linha || ktemp2.equals("\n")) {
          ktemp2 += "\n";
          linha++;
        }

      }
      console = ktemp2;

    }
    catch (IOException e) {
      e.printStackTrace();
    }
    return console;
  }


  public String executeCEditado(String maquina, String projeto, String flag, List<StringBuilder> listOut) throws RemoteException {
    Runtime runtime = Runtime.getRuntime();
    Process process;
    String cmd;
    String console = "";

    try {

      for (StringBuilder fb : listOut)
        setFileProject(fb, maquina, projeto);

      String temp[] = flag.split(" ");
      String file = null;
      for (int i = 0; i < temp.length; i++) {
        if (temp[i].endsWith(".c")) {
          file = temp[i].replace(".c", "");
          break;
        }
      }

      cmd = flag.replace(file, String.format("/home/RMI/GPUHelp-%s/%s/%s", maquina, projeto, file));

      process = runtime.exec(cmd);

      System.out.println(cmd);
      Saida s1 = new Saida();
      process = runtime.exec(cmd);
      s1.saida = new Scanner(process.getInputStream());
      s1.err = new Scanner(process.getErrorStream());
      while (s1.getSaida().hasNext())
        console += new String(("\n" + s1.getSaida().nextLine()).getBytes(), "UTF-8");

      while (s1.getErr().hasNext())
        console += new String(("\n" + s1.getErr().nextLine()).getBytes(), "UTF-8");

      if (console == null || console.isEmpty()) {

        cmd = String.format("/home/RMI/GPUHelp-%s/%s/./%s", maquina, projeto, file.replace(".c", ""));
        process = runtime.exec(cmd);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;

        while ((line = bufferedReader.readLine()) != null)
          console += line;

        System.out.println(console);
      }
      process.destroy();
      console = console.replaceAll(".*/", "").replaceAll("\n", "").trim();
      String ktemp[] = console.split(" ");
      String ktemp2 = "Compilado com sucesso!!!\nResultado do Programa:\n\n\n";
      int linha = 1;
      for (int u = 0; u < ktemp.length; u++) {
        ktemp2 += ktemp[u] + " ";
        if (ktemp2.length() - 50 > 70 * linha || ktemp2.equals("\n")) {
          ktemp2 += "\n";
          linha++;
        }

      }
      console = ktemp2;
    }
    catch (IOException e) {
      e.printStackTrace();
    }
    return console;
  }


  public String executeOpencl(String maquina, StringBuilder fout) throws RemoteException {
    Runtime runtime = Runtime.getRuntime();
    Process process;
    String console = "";

    File f = setFile(fout, maquina);
    String fileName = f.getName();

    Saida s1 = new Saida();
    try {
      String cmd = "";
      if (fileName.endsWith(".c"))
        cmd = String.format("gcc %s -o %s -lOpenCL", // flag opencl para C
            f.getAbsolutePath(), f.getAbsolutePath().replace(".c", ""));
      else
        cmd = String.format("g++ %s -o %s -lOpenCL", // flag opencl para C++
            f.getAbsolutePath(), f.getAbsolutePath().replace(".cpp", ""));

      System.out.println(String.format("A maquina '%s' executou o comando\n'%s' ", maquina, cmd));

      process = runtime.exec(cmd);

      s1.saida = new Scanner(process.getInputStream());
      s1.err = new Scanner(process.getErrorStream());

      while (s1.getSaida().hasNext())
        console += new String(("\n" + s1.getSaida().nextLine()).getBytes(), "UTF-8");

      while (s1.getErr().hasNext())
        console += new String(("\n" + s1.getErr().nextLine()).getBytes(), "UTF-8");

      if (console == null || console.isEmpty()) {

        if (fileName.endsWith(".c"))
          cmd = String.format("/home/RMI/%s/./%s", maquina, fileName.replace(".c", ""));
        else
          cmd = String.format("/home/RMI/%s/./%s", maquina, fileName.replace(".cpp", ""));

        process = runtime.exec(cmd);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;

        while ((line = bufferedReader.readLine()) != null)
          console += line + "\n";

        System.out.println(console);
      }
      process.destroy();

      console = console.replaceAll(".*/", "").replaceAll("\n", "").trim();
      String ktemp[] = console.split(" ");
      String ktemp2 = "Compilado com sucesso!!!\nResultado do Programa:\n\n\n";
      int linha = 1;
      for (int u = 0; u < ktemp.length; u++) {
        ktemp2 += ktemp[u] + " ";
        if (ktemp2.length() - 50 > 70 * linha || ktemp2.equals("\n")) {
          ktemp2 += "\n";
          linha++;
        }

      }
      console = ktemp2;

    }
    catch (IOException e) {
      e.printStackTrace();
    }
    return console;
  }


  public String executeOpenclEditado(String maquina, String projeto, String flag, List<StringBuilder> listOut) throws RemoteException {
    Runtime runtime = Runtime.getRuntime();
    Process process;
    String cmd;
    String console = "";

    for (StringBuilder fb : listOut)
      setFileProject(fb, maquina, projeto);

    try {
      String temp[] = flag.split(" ");
      String file = null;
      for (int i = 0; i < temp.length; i++) {
        if (temp[i].endsWith(".c") || temp[i].endsWith(".cpp") || temp[i].endsWith(".cl")) {
          file = temp[i].substring(0, temp[i].lastIndexOf("."));
          break;
        }
      }

      cmd = flag.replace(file, String.format("/home/RMI/GPUHelp-%s/%s/%s", maquina, projeto, file));

      System.out.println(cmd);

      process = runtime.exec(cmd);
      System.out.println(cmd);
      Saida s1 = new Saida();
      process = runtime.exec(cmd);
      s1.saida = new Scanner(process.getInputStream());
      s1.err = new Scanner(process.getErrorStream());
      while (s1.getSaida().hasNext())
        console += new String(("\n" + s1.getSaida().nextLine()).getBytes(), "UTF-8");

      while (s1.getErr().hasNext())
        console += new String(("\n" + s1.getErr().nextLine()).getBytes(), "UTF-8");

      if (console == null || console.isEmpty()) {

        cmd = String.format("/home/RMI/GPUHelp-%s/%s/./%s", maquina, projeto, file);
        System.out.println(cmd);
        process = runtime.exec(cmd);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;

        while ((line = bufferedReader.readLine()) != null)
          console += line;

        System.out.println(console);
      }
      process.destroy();
      console = console.replaceAll(".*/", "").replaceAll("\n", "").trim();
      String ktemp[] = console.split(" ");
      String ktemp2 = "Compilado com sucesso!!!\nResultado do Programa:\n\n\n";
      int linha = 1;
      for (int u = 0; u < ktemp.length; u++) {
        ktemp2 += ktemp[u] + " ";
        if (ktemp2.length() - 50 > 70 * linha || ktemp2.equals("\n")) {
          ktemp2 += "\n";
          linha++;
        }

      }
      console = ktemp2;
    }
    catch (IOException e) {
      e.printStackTrace();
    }
    return console;
  }


  public String executeCuda(String maquina, StringBuilder fout) throws RemoteException {
    Runtime runtime = Runtime.getRuntime();
    Process process;
    String console = "";

    File f = setFile(fout, maquina);
    String fileName = f.getName();

    Saida s1 = new Saida();
    try {

      String cmd = String.format("nvcc %s -o %s -lstdc++", f.getAbsolutePath(), f // flag cuda
          .getAbsolutePath().replace(".cu", ""));

      System.out.println(String.format("A maquina '%s' executou o comando\n'%s' ", maquina, cmd));

      process = runtime.exec(cmd);

      s1.saida = new Scanner(process.getInputStream());
      s1.err = new Scanner(process.getErrorStream());

      while (s1.getSaida().hasNext())
        console += new String(("\n" + s1.getSaida().nextLine()).getBytes(), "UTF-8");

      while (s1.getErr().hasNext())
        console += new String(("\n" + s1.getErr().nextLine()).getBytes(), "UTF-8");

      if (console == null || console.isEmpty()) {

        cmd = String.format("/home/RMI/%s/./%s", maquina, fileName.replace(".cu", ""));

        process = runtime.exec(cmd);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;

        while ((line = bufferedReader.readLine()) != null)
          console += line + "\n";

        System.out.println(console);
      }
      process.destroy();

      console = console.replaceAll(".*/", "").replaceAll("\n", "").trim();
      String ktemp[] = console.split(" ");
      String ktemp2 = "Compilado com sucesso!!!\nResultado do Programa:\n\n\n";
      int linha = 1;
      for (int u = 0; u < ktemp.length; u++) {
        ktemp2 += ktemp[u] + " ";
        if (ktemp2.length() - 50 > 70 * linha || ktemp2.equals("\n")) {
          ktemp2 += "\n";
          linha++;
        }

      }
      console = ktemp2;

    }
    catch (IOException e) {
      e.printStackTrace();
    }
    return console;
  }


  public String executeCudaEditado(String maquina, String projeto, String flag, List<StringBuilder> listOut) throws RemoteException {
    Runtime runtime = Runtime.getRuntime();
    Process process;
    String cmd;
    String console = "";

    for (StringBuilder fb : listOut)
      setFileProject(fb, maquina, projeto);

    try {
      String temp[] = flag.split(" ");
      String file = null;
      for (int i = 0; i < temp.length; i++) {
        if (temp[i].endsWith(".cu")) {
          file = temp[i].replace(".cu", "");
          break;
        }
      }

      cmd = flag.replace(file, String.format("/home/RMI/GPUHelp-%s/%s/%s", maquina, projeto, file));
      process = runtime.exec(cmd);
      System.out.println(cmd);
      Saida s1 = new Saida();
      process = runtime.exec(cmd);
      s1.saida = new Scanner(process.getInputStream());
      s1.err = new Scanner(process.getErrorStream());
      while (s1.getSaida().hasNext())
        console += new String(("\n" + s1.getSaida().nextLine()).getBytes(), "UTF-8");

      while (s1.getErr().hasNext())
        console += new String(("\n" + s1.getErr().nextLine()).getBytes(), "UTF-8");

      if (console == null || console.isEmpty()) {

        cmd = String.format("/home/RMI/GPUHelp-%s/%s/./%s", maquina, projeto, file.replace(".cu", ""));
        process = runtime.exec(cmd);
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String line;

        while ((line = bufferedReader.readLine()) != null)
          console += line;

        System.out.println(console);
      }
      process.destroy();
      console = console.replaceAll(".*/", "").replaceAll("\n", "").trim();
      String ktemp[] = console.split(" ");
      String ktemp2 = "Compilado com sucesso!!!\nResultado do Programa:\n\n\n";
      int linha = 1;
      for (int u = 0; u < ktemp.length; u++) {
        ktemp2 += ktemp[u] + " ";
        if (ktemp2.length() - 50 > 70 * linha || ktemp2.equals("\n")) {
          ktemp2 += "\n";
          linha++;
        }

      }
      console = ktemp2;

    }
    catch (IOException e) {
      e.printStackTrace();
    }

    return console;
  }


  public String getStatus(String maquina, String usuario) throws RemoteException {
    String status = String.format("O usuario '%s' conectou do PC %s em %s ", usuario, maquina, getDate());
    System.out.println(status);
    return status;
  }


  public File setFile(StringBuilder fb, String maquina) {
    try {
      File file = new File(String.format("/home/RMI/%s", maquina));

      try {
        file.mkdir();
      }
      catch (Exception ef) {
        // ef.printStackTrace();
      }

      String temp[] = fb.toString().split("\n");
      file = new File(String.format("/home/RMI/%s/%s", maquina, temp[0].replace("//", "").trim()));
      FileWriter fw = new FileWriter(file);
      fw.write(fb.toString());
      fw.close();
      return file;
    }
    catch (Exception ef) {
      // ef.printStackTrace();
    }

    return null;
  }


  public File setFileProject(StringBuilder fb, String maquina, String projeto) {
    try {
      String pathProjetp = String.format("/home/RMI/GPUHelp-%s/%s/", maquina, projeto);
      File file = new File(String.format("/home/RMI/GPUHelp-%s", maquina));
      // ManipulaArquivos.getInstance().delete(file);
      try {
        file.mkdir();
      }
      catch (Exception ef) {
        // ef.printStackTrace();
      }
      file = new File(String.format("/home/RMI/GPUHelp-%s/%s", maquina, projeto));

      try {
        file.mkdir();
      }
      catch (Exception ef) {
        // ef.printStackTrace();
      }

      String temp[] = fb.toString().split("\n");
      file = new File(String.format("/home/RMI/GPUHelp-%s/%s/%s", maquina, projeto, temp[0].replace("//", "").trim()));
      FileWriter fw = new FileWriter(file);
      fw.write(fb.toString().replace("const char *sourceFile = \"", "const char *sourceFile = \"" + pathProjetp));
      fw.close();
      return file;
    }
    catch (Exception ef) {
      // ef.printStackTrace();
    }

    return null;
  }


  public String getDate() {
    DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyy HH:mm:ss");
    Date date = new Date();
    return dateFormat.format(date);
  }

}
